// Copyright 2023 The Cockroach Authors.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

package allocator2

import "github.com/cockroachdb/cockroach/pkg/roachpb"

// Incoming messages for updating cluster state.
//
// This is a stop-gap and we will substitute these with protos.
//
// TODO(sumeer): add corresponding protos.

// storeLoadMsg is periodically sent by each store.
type storeLoadMsg struct {
	roachpb.StoreID

	load loadVector
	// storeRanges are only used for adjusting the accounting for load
	// adjustments for pending changes. This is *all* the ranges at the store.
	storeRanges []storeRange

	capacity      loadVector
	secondaryLoad secondaryLoadVector
	topKRanges    []struct {
		roachpb.RangeID
		rangeLoad
	}
	meanNonTopKRangeLoad rangeLoad
}

// storeRange is basic information about a range at a store, and is included
// in storeLoadMsg.
type storeRange struct {
	// We don't bother with ReplicaID since only used for load adjustments.
	roachpb.RangeID
	// Only valid ReplicaTypes are used here.
	replicaType
}

// storeLeaseholderMsg is sent by a store and includes information about all
// ranges for which this store is the leaseholder. The range information
// includes other replica stores.
type storeLeaseholderMsg struct {
	roachpb.StoreID

	// NB: storeLoadMsg.storeRanges and storeLeaseholderMsg.ranges do not need
	// to be consistent. This ranges is providing authoritative information from
	// the leaseholder. storeRanges can lag in that the store may not include a
	// range or the fact that this store is the leaseholder, if the effect of
	// that range on the load is not yet properly accounted for.
	ranges []rangeMsg
}

// rangeMsg is generated by the leaseholder store (and part of
// storeLeaseholderMsg). If there is any change for that range, the full
// information for that range is provided. This is also the case for a new
// leaseholder since it does not know whether something has changed since the
// last leaseholder informed the allocator.
//
// Also used in a best-effort manner to tell the allocator of ranges that no
// longer exist.
type rangeMsg struct {
	roachpb.RangeID
	start    roachpb.Key
	end      roachpb.Key
	replicas []storeIDAndReplicaState
	conf     roachpb.SpanConfig
}

func (rm *rangeMsg) isDeletedRange() bool {
	return len(rm.replicas) == 0
}

// nodeLoadResponse is sent periodically in response to polling by the
// allocator. It is the top-level message containing all the previous structs
// declared in this file.
type nodeLoadResponse struct {
	// -1 if this nodeLoadMsg is not a diff. Responder can unilaterally send a
	// complete load even if the sender asked for a diff.
	//
	// TODO(sumeer): the diff story is not properly fleshed out for the local
	// node in a distributed allocator, since there are also other updates via
	// AdjustPendingChangesDisposition. We can start with only full state
	// updates, and add diff support later.
	lastLoadSeqNum int64
	curLoadSeqNum  int64

	nodeLoad
	stores            []storeLoadMsg
	leaseholderStores []storeLeaseholderMsg
}

// nodeLoadRequest is the request corresponding to nodeLoadResponse.
type nodeLoadRequest struct {
	// Set to -1 if desire a complete load.
	lastReceivedLoadSeqNum int64
}

// Avoid unused lint errors.

var _ = (&rangeMsg{}).isDeletedRange
var _ = nodeLoadRequest{}
var _ = storeLoadMsg{}.StoreID
var _ = storeLoadMsg{}.load
var _ = storeLoadMsg{}.storeRanges
var _ = storeLoadMsg{}.capacity
var _ = storeLoadMsg{}.secondaryLoad
var _ = storeLoadMsg{}.topKRanges
var _ = storeLoadMsg{}.meanNonTopKRangeLoad
var _ = storeRange{}.RangeID
var _ = storeRange{}.replicaType
var _ = storeLeaseholderMsg{}.StoreID
var _ = storeLeaseholderMsg{}.ranges
var _ = rangeMsg{}.RangeID
var _ = rangeMsg{}.start
var _ = rangeMsg{}.end
var _ = rangeMsg{}.replicas
var _ = rangeMsg{}.conf
var _ = nodeLoadResponse{}.lastLoadSeqNum
var _ = nodeLoadResponse{}.curLoadSeqNum
var _ = nodeLoadResponse{}.nodeLoad
var _ = nodeLoadResponse{}.stores
var _ = nodeLoadResponse{}.leaseholderStores
var _ = nodeLoadRequest{}.lastReceivedLoadSeqNum
